package com.douziit.meilianoa.base.utils.file;

import org.apache.tomcat.util.http.fileupload.FileUploadException;
import org.apache.tomcat.util.http.fileupload.servlet.ServletFileUpload;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Random;

/**
 * @author songcl
 * @2016年3月17日
 */
public class UploadDocumentUtil {
	private static final Logger logger = LoggerFactory.getLogger(UploadDocumentUtil.class);

	/**
	 * 上传到其他指定目录的文件
	 *
	 * @param input
	 * @param fileName
	 * @param baseDir
	 *            带"/"的文件夹全路径
	 *            子目录
	 */
	public static String uploadFile(InputStream input, String fileName, String baseDir) throws IOException {

		String savePath = baseDir;
		// 检查目录
		File uploadDir = new File(baseDir);
		if (!uploadDir.exists()) {
			uploadDir.mkdirs();
		}
		logger.info("全路径名:"+uploadDir.getAbsolutePath());
		if (!uploadDir.isDirectory()) {
			logger.error("please select upload file, it is dir");
			return null;
		}

		// 检查目录写权限
		if (!uploadDir.canWrite()) {
			logger.error("upload file, cannot write to this dir");
			throw new IOException("upload file, cannot write to this dir");
		}

		// 文件保存目录URL
		String saveUrl = "";
		// 按日期分子目录存储
		SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
		String ymd = sdf.format(new Date());
		savePath += ymd + "/";
		saveUrl += ymd + "/";
		File dirFile = new File(savePath);
		if (!dirFile.exists()) {
			dirFile.mkdirs();
		}

		String fileExt = fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();
		SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");
		String newFileName = df.format(new Date()) + "_" + new Random().nextInt(1000) + "." + fileExt;

		saveUrl += newFileName;

		logger.info("save file, name:" + saveUrl);

		FileOutputStream fos = new FileOutputStream(savePath + newFileName);
		byte[] buffer = new byte[2048];

		try {
			int num = 0;
			while ((num = input.read(buffer)) > 0) {
				fos.write(buffer, 0, num);
			}
		} catch (IOException ex) {
			logger.error("save file exception:" + saveUrl, ex);
			throw ex;
		} finally {
			try {
				if (fos != null)
					fos.close();
			} catch (IOException e) {
			}
		}

		return saveUrl;
	}

	/**
	 * 上传到其他指定目录的文件
	 *
	 * @param input
	 * @param fileName
	 * @param baseDir
	 *            带"/"的文件夹全路径
	 *            子目录
	 */
	public static String uploadOriginalFile(InputStream input, String fileName, String baseDir) throws IOException {

		// 检查目录
		File uploadDir = new File(baseDir);
		if (!uploadDir.exists()) {
			uploadDir.mkdirs();
		}

		if (!uploadDir.isDirectory()) {
			logger.error("please select upload file, it is dir");
			return null;
		}

		// 检查目录写权限
		if (!uploadDir.canWrite()) {
			logger.error("upload file, cannot write to this dir");
			throw new IOException("upload file, cannot write to this dir");
		}

		// 文件保存目录URL
		String saveUrl = fileName.substring(0,fileName.lastIndexOf(".")) + "_original" + fileName.substring(fileName.lastIndexOf("."));

		String savePath = baseDir + saveUrl;

		logger.info("save file, name:" + saveUrl);

		FileOutputStream fos = new FileOutputStream(savePath);
		byte[] buffer = new byte[2048];

		try {
			int num = 0;
			while ((num = input.read(buffer)) > 0) {
				fos.write(buffer, 0, num);
			}
		} catch (IOException ex) {
			logger.error("save file exception:" + saveUrl, ex);
			throw ex;
		} finally {
			try {
				if (fos != null)
					fos.close();
			} catch (IOException e) {
			}
		}

		return saveUrl;
	}


	/**
	 * 上传到WebApp目录下的文件
	 * 
	 * @param request
	 * @param input
	 * @param fileName
	 * @param dirName
	 *            子目录
	 * @param prefix
	 * @return
	 * @throws FileUploadException
	 * @throws IOException
	 */
	public static String upload(HttpServletRequest request, InputStream input, String fileName, String dirName,
                                String prefix) throws IOException {
		// 文件是否存在
		if (!ServletFileUpload.isMultipartContent(request)) {
			logger.error("please select upload file");
			throw new IllegalArgumentException("please select upload file");
		}

		String savePath = request.getServletContext().getRealPath("/") + dirName + "/";
		// 检查目录
		File uploadDir = new File(savePath);
		if (!uploadDir.exists()) {
			uploadDir.mkdirs();
		}

		if (!uploadDir.isDirectory()) {
			logger.error("please select upload file, it is dir");
			return null;
		}

		// 检查目录写权限
		if (!uploadDir.canWrite()) {
			logger.error("upload file, cannot write to this dir");
			throw new IOException("upload file, cannot write to this dir");
		}

		// 文件保存目录URL
		String saveUrl = request.getContextPath() + "/" + dirName + "/";
		// 按日期分子目录存储
		SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
		String ymd = sdf.format(new Date());
		savePath += ymd + "/";
		saveUrl += ymd + "/";
		File dirFile = new File(savePath);
		if (!dirFile.exists()) {
			dirFile.mkdirs();
		}

		String fileExt = fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();
		SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");
		String newFileName = prefix + "_" + df.format(new Date()) + "_" + new Random().nextInt(1000) + "." + fileExt;

		saveUrl += newFileName;

		logger.info("save file, name:" + saveUrl);

		FileOutputStream fos = new FileOutputStream(savePath + newFileName);
		byte[] buffer = new byte[2048];

		try {
			int num = 0;
			while ((num = input.read(buffer)) > 0) {
				fos.write(buffer, 0, num);
			}
		} catch (IOException ex) {
			logger.error("save file exception:" + saveUrl, ex);
			throw ex;
		} finally {
			try {
				if (fos != null)
					fos.close();
			} catch (IOException e) {
			}
		}

		return saveUrl;
	}

	/**
	 * 上传到其他指定目录的文件
	 * 
	 * @param request
	 * @param input
	 * @param fileName
	 * @param baseDir
	 *            带"/"的文件夹全路径
	 * @param dirName
	 *            子目录
	 * @param prefix
	 * @return
	 * @throws FileUploadException
	 * @throws IOException
	 */
	public static String uploadPrivate(HttpServletRequest request, InputStream input, String fileName, String baseDir,
                                       String dirName, String prefix) throws IOException {
		// 文件是否存在
		if (!ServletFileUpload.isMultipartContent(request)) {
			logger.error("please select upload file");
			throw new IllegalArgumentException("please select upload file");
		}

		String savePath = baseDir + dirName + "/";
		// 检查目录
		File uploadDir = new File(baseDir);
		if (!uploadDir.exists()) {
			uploadDir.mkdirs();
		}

		if (!uploadDir.isDirectory()) {
			logger.error("please select upload file, it is dir");
			return null;
		}

		// 检查目录写权限
		if (!uploadDir.canWrite()) {
			logger.error("upload file, cannot write to this dir");
			throw new IOException("upload file, cannot write to this dir");
		}

		// 文件保存目录URL
		String saveUrl = dirName + "/";
		// 按日期分子目录存储
		SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
		String ymd = sdf.format(new Date());
		savePath += ymd + "/";
		saveUrl += ymd + "/";
		File dirFile = new File(savePath);
		if (!dirFile.exists()) {
			dirFile.mkdirs();
		}

		String fileExt = fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();
		SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");
		String newFileName = prefix + "_" + df.format(new Date()) + "_" + new Random().nextInt(1000) + "." + fileExt;

		saveUrl += newFileName;

		logger.info("save file, name:" + saveUrl);

		FileOutputStream fos = new FileOutputStream(savePath + newFileName);
		byte[] buffer = new byte[2048];

		try {
			int num = 0;
			while ((num = input.read(buffer)) > 0) {
				fos.write(buffer, 0, num);
			}
		} catch (IOException ex) {
			logger.error("save file exception:" + saveUrl, ex);
			throw ex;
		} finally {
			try {
				if (fos != null)
					fos.close();
			} catch (IOException e) {
			}
		}

		return saveUrl;
	}

	/**
	 * 上传文件
	 * 
	 * @param request
	 * @param file
	 * @param fileName
	 * @param dirName
	 * @return
	 * @throws FileUploadException
	 * @throws IOException
	 */
	public static String upload(HttpServletRequest request, File file, String fileName, String dirName)
			throws FileUploadException, IOException {
		String savePath = request.getServletContext().getRealPath("/") + dirName + "/";
		File test = new File(savePath);
		if (!test.exists()) {
			test.mkdirs();
		}

		// 文件保存目录URL
		String saveUrl = request.getContextPath() + "/" + dirName + "/";
		// 定义允许上传的文件扩展名
		// HashMap<String, String> extMap = new HashMap<String, String>();
		// extMap.put("images", "gif,jpg,jpeg,png,bmp");
		// extMap.put("flash", "swf,flv");
		// extMap.put("media",
		// "swf,flv,mp3,wav,wma,wmv,mid,avi,mpg,asf,rm,rmvb");
		// extMap.put("file",
		// "doc,docx,xls,xlsx,ppt,htm,html,txt,zip,rar,gz,bz2");

		// 文件是否存在
		if (!ServletFileUpload.isMultipartContent(request)) {
			logger.error("please select upload file");
			return null;
		}

		// 检查目录
		File uploadDir = new File(savePath);
		if (!uploadDir.isDirectory()) {
			logger.error("please select upload file, it is dir");
			return null;
		}

		// 检查目录写权限
		if (!uploadDir.canWrite()) {
			logger.error("upload file, cannot write to this dir");
			return null;
		}

		// String dirName = request.getParameter("dir");
		// if (dirName == null) {
		// dirName = "images";
		// }
		// if (!extMap.containsKey(dirName)) {
		// logger.error("upload file, dir is error");
		// return null;
		// }

		// 创建文件夹
		// savePath += dirName + "/";
		// saveUrl += dirName + "/";
		// File saveDirFile = new File(savePath);
		// if (!saveDirFile.exists()) {
		// saveDirFile.mkdirs();
		// }

		// 按日期分子目录存储
		SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
		String ymd = sdf.format(new Date());
		savePath += ymd + "/";
		saveUrl += ymd + "/";
		File dirFile = new File(savePath);
		if (!dirFile.exists()) {
			dirFile.mkdirs();
		}

		String fileExt = fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();
		// if (!Arrays.<String>
		// asList(extMap.get(dirName).split(",")).contains(fileExt)) {
		// logger.error("upload file, unsupport file:" + fileExt);
		// return null;
		// }
		SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");
		String newFileName = df.format(new Date()) + "_" + new Random().nextInt(1000) + "." + fileExt;

		saveUrl += newFileName;

		logger.info("save file, name:" + saveUrl);

		FileOutputStream fos = new FileOutputStream(savePath + newFileName);
		byte[] buffer = new byte[2048];
		InputStream in = new FileInputStream(file);
		try {
			int num = 0;
			while ((num = in.read(buffer)) > 0) {
				fos.write(buffer, 0, num);
			}
		} catch (IOException ex) {
			throw ex;
		} catch (Exception e) {
			logger.error("save file exception:" + saveUrl, e);
			return null;
		} finally {
			try {
				if (in != null)
					in.close();
				if (fos != null)
					fos.close();
			} catch (IOException e) {
			}
		}

		return saveUrl;
	}

	/**
	 * 指定磁盘路径上传多文件 返回文件名  逗号隔开
	 *
	 * @param path  磁盘路径   例  "D:/assistive/"
	 * @param files 指定上传的文件数组
	 * @return 返回文件名  逗号隔开 "D:/assistive/20200716/20200716173907_338.png,D:/assistive/20200716/20200716173907_732.png,"
	 */
	public static String uploadFiles(String path, MultipartFile[] files) throws IOException {
		//空文件组退出
		if (files == null || files.length == 0) {
			return "";
		}
		StringBuffer sb = new StringBuffer();
		SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");
		// 按日期分子目录存储
		SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
		String ymd ="".concat( sdf.format(new Date()));
		path += ymd + "/";

		for (MultipartFile file : files) {
			System.out.println(path);
			File dirFile = new File(path);
			if (!dirFile.exists()) {
				dirFile.mkdirs();
			}
			// 检查目录写权限
			if (!dirFile.canWrite()) {
				logger.error("upload file, cannot write to this dir");
				throw new IOException("upload file, cannot write to this dir");
			}
			String fileExt = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf(".") + 1).toLowerCase();
			String fileName = df.format(new Date()) + "_" + new Random().nextInt(1000) + "." + fileExt;
			String newFileName = path.concat(fileName);
			File saveFile = new File(newFileName);
			// 转存文件
			file.transferTo(saveFile);
			//网络路径做Nginx映射 Windows环境截除磁盘D:E:F: 盘符  Linux路径无需截除  域名端口前端自行配置
			if (newFileName.indexOf(":") != -1) {
				sb.append(newFileName.substring(newFileName.indexOf(":") + 1)).append(",");
			} else {
				sb.append(newFileName).append(",");
			}
		}
		return sb.toString().substring(0, sb.toString().length() - 1);
	}
}
